package com.soo.hoo.admin.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNode;
import cn.hutool.core.lang.tree.TreeUtil;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.soo.hoo.admin.mapper.SysPermissionMapper;
import com.soo.hoo.admin.model.dto.RoleDTO;
import com.soo.hoo.admin.model.entity.SysPermission;
import com.soo.hoo.admin.service.PermissionService;
import com.soo.hoo.core.constant.Constants;
import com.soo.hoo.core.exception.GlobalException;
import com.soo.hoo.core.model.MatchItem;
import com.soo.hoo.core.model.Page;
import com.soo.hoo.core.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * <p>权限管理服务</p>
 *
 * @author 杨燚
 * @since 2023/4/3
 */
@Service
public class PermissionServiceImpl extends ServiceImpl<SysPermissionMapper, SysPermission> implements PermissionService {

    @Override
    public List<Tree<Long>> getPermissionTree() {
        LambdaQueryWrapper<SysPermission> lqw = new LambdaQueryWrapper<SysPermission>()
                .eq(SysPermission::getEnabled, true);
        List<SysPermission> permissions = baseMapper.selectList(lqw);
        List<TreeNode<Long>> treeNodes = new ArrayList<>();
        for (SysPermission permission : permissions) {
            TreeNode<Long> node = new TreeNode<>();
            node.setId(permission.getId());
            node.setParentId(permission.getParentId());
            node.setName(permission.getPermissionName());
            node.setWeight(permission.getWeight());
            treeNodes.add(node);
        }
        return TreeUtil.build(treeNodes, Constants.ROOT_ID);
    }

    @Override
    public List<Tree<Long>> tree(List<MatchItem> matchItems) {
        Page<SysPermission> page = new Page<>();
        page.setMatchItems(matchItems);
        Wrapper<SysPermission> wrapper = page.wrapper();
        List<SysPermission> permissions = baseMapper.selectList(wrapper);
        if (CollUtil.isEmpty(permissions)) {
            return new ArrayList<>(0);
        }
        return buildTree(permissions);
    }

    @Override
    public void removeChildren(Long id) {
        String[] means = {"系统设置", "用户管理", "角色管理", "权限管理"};
        SysPermission permission = baseMapper.selectById(id);
        if (Arrays.asList(means).contains(permission.getPermissionName())) {
            throw new GlobalException("系统菜单暂不支持删除");
        }
        // 删除自身以及其所有子权限
        List<SysPermission> permissions = baseMapper.selectList(Wrappers.emptyWrapper());
        List<SysPermission> deleteList = listChildren(permissions, id);
        if (CollUtil.isNotEmpty(deleteList)) {
            for (SysPermission del : deleteList) {
                baseMapper.deleteById(del.getId());
            }
        }
        baseMapper.deleteById(id);
    }

    /**
     * 遍历出所有子类
     *
     * @param list   全部列表
     * @param rootId 父类id
     * @return 子类
     */
    private List<SysPermission> listChildren(List<SysPermission> list, Long rootId) {
        List<SysPermission> retList = new ArrayList<>();
        List<SysPermission> children = list.stream().filter(e -> e.getParentId().equals(rootId)).toList();
        if (CollUtil.isNotEmpty(children)) {
            for (SysPermission child : children) {
                retList.add(child);
                retList.addAll(listChildren(list, child.getId()));
            }
        }
        return retList;
    }

    /**
     * 初始化角色权限
     */
    @Override
    public void initPermission() {
        LambdaQueryWrapper<SysPermission> lqw = new LambdaQueryWrapper<SysPermission>()
                .eq(SysPermission::getParentId, 0)
                .eq(SysPermission::getPermissionName, "系统设置")
                .eq(SysPermission::getType, 1);
        SysPermission sysManage = baseMapper.selectOne(lqw);
        //至少有一个菜单，“系统设置”-》“用户管理”、“角色管理”、“权限管理”
        if (sysManage == null) {
            sysManage = new SysPermission();
            sysManage.setParentId(Constants.ROOT_ID);
            sysManage.setPermissionName("系统设置");
            sysManage.setType(1);
            sysManage.setIconName("Setting");
            sysManage.setIconColor("#C71585");
            sysManage.setWeight(0);
            sysManage.setDescription("系统设置菜单");
            sysManage.setHasChildren(true);
            baseMapper.insert(sysManage);
            SysPermission userManage = new SysPermission();
            userManage.setParentId(sysManage.getId());
            userManage.setPermissionName("用户管理");
            userManage.setType(1);
            userManage.setIconName("User");
            userManage.setIconColor("#22C3AA");
            userManage.setUrl("/setting/user");
            userManage.setWeight(3);
            userManage.setDescription("用户管理");
            baseMapper.insert(userManage);
            SysPermission roleManage = new SysPermission();
            roleManage.setParentId(sysManage.getId());
            roleManage.setPermissionName("角色管理");
            roleManage.setType(1);
            roleManage.setIconName("Postcard");
            roleManage.setIconColor("#1E90FF");
            roleManage.setUrl("/setting/role");
            roleManage.setWeight(2);
            roleManage.setDescription("角色管理");
            baseMapper.insert(roleManage);
            SysPermission permissionManage = new SysPermission();
            permissionManage.setParentId(sysManage.getId());
            permissionManage.setPermissionName("权限管理");
            permissionManage.setType(1);
            permissionManage.setIconName("Notebook");
            permissionManage.setIconColor("#FF8C00");
            permissionManage.setUrl("/setting/permission");
            permissionManage.setWeight(1);
            permissionManage.setDescription("权限管理");
            baseMapper.insert(permissionManage);
        }
    }

    @Override
    public void verifyPermission(Long parentId, String permissionName) {
        LambdaQueryWrapper<SysPermission> lqw = new LambdaQueryWrapper<SysPermission>()
                .eq(SysPermission::getParentId, parentId)
                .eq(SysPermission::getPermissionName, permissionName);
        List<SysPermission> list = baseMapper.selectList(lqw);
        if (CollUtil.isNotEmpty(list)) {
            throw new GlobalException("相同目录下已存在【" + permissionName + "】权限，请确认是否添加重复权限信息");
        }
    }

    @Override
    public Map<Long, RoleDTO> mapRolePermission(Collection<Long> roleIds) {
        List<RoleDTO> rolePermissions = baseMapper.selectPermissionByRoleIds(roleIds);
        return rolePermissions.stream()
                .collect(Collectors.toMap(RoleDTO::getId, Function.identity(), (o1, o2) -> o2));
    }

    /**
     * 构建权限树形结构数据
     *
     * @param permissions 权限列表
     * @return 树形结构
     */
    private List<Tree<Long>> buildTree(List<SysPermission> permissions) {
        List<TreeNode<Long>> treeNodes = new ArrayList<>();
        for (SysPermission permission : permissions) {
            TreeNode<Long> node = new TreeNode<>();
            node.setId(permission.getId());
            node.setParentId(permission.getParentId());
            node.setName(permission.getPermissionName());
            node.setWeight(permission.getWeight());
            Map<String, Object> extra = new HashMap<>(8);
            extra.put("type", permission.getType());
            extra.put("url", permission.getUrl());
            extra.put("iconName", permission.getIconName());
            extra.put("iconColor", permission.getIconColor());
            extra.put("enabled", permission.getEnabled());
            extra.put("description", permission.getDescription());
            node.setExtra(extra);
            treeNodes.add(node);
        }
        return TreeUtil.build(treeNodes, Constants.ROOT_ID);
    }
}
